package com.bro.person.admin.service.impl;

import com.bro.person.admin.model.AdminResource;
import com.bro.person.admin.model.AdminUser;
import com.bro.person.admin.service.IAdminResourceService;
import com.bro.person.admin.service.IAdminUserService;
import com.bro.person.admin.service.ISecurityService;
import com.bro.person.admin.struct.AdminMenuStruct;
import com.bro.person.admin.struct.SecurityAuthenticateResultStruct;
import com.bro.person.admin.struct.SecurityPermissionStruct;
import com.bro.person.admin.struct.SecurityUserStruct;
import com.bro.person.admin.utils.AuthorityConvertUtil;
import com.bro.person.admin.utils.ValidateModelUtil;
import com.bro.person.base.enums.error.GlobalEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author swallow
 * Created by swallow on 2018/11/2.<br>
 */
@Service(value = "wySecurityService")
public class SecurityServiceImpl implements ISecurityService {

    private static final Logger logger = LoggerFactory.getLogger(SecurityServiceImpl.class);

    @Autowired
    private IAdminUserService adminUserService;

    @Autowired
    private IAdminResourceService adminResourceService;

    /**
     * 查询用户是否有对应权限
     * @param userId
     * @param url 访问url
     * @return
     */
    @Override
    public boolean checkAuthentication(int userId, String url) {
        logger.debug("[SecurityServiceImpl][checkAuthentication] entering userId:{},url:{}",userId, url);
        boolean flag = false;
        // 过滤参数
        if(StringUtils.isNotBlank(url)){
            //判断当前的url 是否是共有链接
            List<AdminResource> resourceList = adminResourceService.queryAll();
            if(resourceList!=null && resourceList.size()>0 && resourceList.get(0)!=null){
                AdminUser wyAdminUser = adminUserService.loadById(userId);
                if(ValidateModelUtil.isAdminUserValid(wyAdminUser)){
                    //通过 userId, status(用户的) 获取用户对应的 permissionCode 集合
                    List<AdminResource> adminResources = adminResourceService.queryResourcesByUserId(wyAdminUser);
                    if(adminResources!=null && adminResources.size()>0){
                        //请求数据不为空
                        flag = checkAuthentication(url,adminResources,0);
                    }
                }
                if(!flag){
                    //判断是否在共有链接中
                    flag = checkAuthentication(url,resourceList,1);
                }
            }
        }
        logger.info("[SecurityServiceImpl][checkAuthentication] 查询用户是否有权限 userId:{},url:{},flag:{}",userId, url, flag);
        return flag;
    }

    /**
     * 查询url是否在 管理权限列表中
     * @param url
     * @param adminResourceList
     * @param isCommon
     * @return
     */
    private boolean checkAuthentication(String url,List<AdminResource> adminResourceList,int isCommon){
        logger.debug("[SecurityServiceImpl][checkAuthentication] entering url:{},adminResourceList:{},isCommon:{}",url, adminResourceList, isCommon);
        boolean flag = false;
        //固定为1 以后可以设置为变量
        int adminResourceListSize = adminResourceList.size();
        for (AdminResource adminResource : adminResourceList) {
            String permissionUrl = adminResource.getUrl();
            if(permissionUrl.contains("%")){
                String[] securityUrlSplitArray = permissionUrl.split("/");
                String[] treadUrlSplitArray = url.split("/");
                //特殊规定
                if(securityUrlSplitArray.length<1 || treadUrlSplitArray.length<1 || securityUrlSplitArray.length!=treadUrlSplitArray.length){
                    flag = false;
                }else{
                    int i = 0;
                    for (; i < securityUrlSplitArray.length; i++) {
                        if("%".equals(securityUrlSplitArray[i])){
                            continue;
                        }else if(!securityUrlSplitArray[i].equals(treadUrlSplitArray[i])){
                            break;
                        }
                    }
                    if(i==securityUrlSplitArray.length){
                        flag = true;
                        break;
                    }
                }
            }else if(permissionUrl.equals(url)){
                flag = true;
                break;
            }
            adminResourceListSize--;
        }
        //排除 非共有链接方法的 参数
        if(isCommon==1 && flag){
            flag = false;
        }
        if(!flag && isCommon==1 && adminResourceListSize==0){
            flag = true;
        }
        return flag;
    }

    @Override
    public SecurityAuthenticateResultStruct authenticate(String username, String password) {
        logger.debug("[SecurityServiceImpl][authenticate] entering username:{},password:{}",username, password);
        // 1.验证账户 这地方要求是password 只为空或者只为空字符串 则为错误密码
        if(StringUtils.isBlank(username) || StringUtils.isBlank(password)){
            // 返回参数错误
            return new SecurityAuthenticateResultStruct(GlobalEnum.BRO_ADMIN_PARAM_EROOR);
        }

        // 通过username 获取对应的用户信息
        AdminUser adminUser = adminUserService.loadCacheByUsername(username);
        //验证 用户的是否是合法用户
        if(!ValidateModelUtil.isAdminUserValid(adminUser)){
            // 用户不存在
            logger.error("[SecurityServiceImpl][authenticate] 用户不存在 username:{},password:{},adminUserId:{}",username, password, adminUser.getId());
            return new SecurityAuthenticateResultStruct(GlobalEnum.BRO_USER_NOT_EXIST_ERROR);
        }
        if(!DigestUtils.md5Hex(password).toLowerCase().equals(adminUser.getPassword())){
            // 密码不匹配
            logger.error("[SecurityServiceImpl][authenticate] 密码不匹配 username:{},password:{},adminPassword:{}",username, password, adminUser.getPassword());
            return new SecurityAuthenticateResultStruct(GlobalEnum.BRO_USER_PASSWORD_ERROR);
        }

        //2. 构建权限数据
        SecurityAuthenticateResultStruct result = new SecurityAuthenticateResultStruct();
        List<AdminResource> adminResources = adminResourceService.queryResourcesByUserId(adminUser);
        //通过 当前用户获取对应的 用户角色列表(感觉没必要) 以及 权限code
        if(adminResources!=null){
            //获取权限数据，mock
            List<SecurityPermissionStruct> permissionList = AuthorityConvertUtil.convert2PermissionStructList(adminResources);
            result.setPermissionList(permissionList);
            SecurityUserStruct securityUserStruct = new SecurityUserStruct();
            securityUserStruct.setUsername(username);
            securityUserStruct.setNickname(adminUser.getNickname());
            securityUserStruct.setUserId(adminUser.getId());
            Date newTime = adminUser.getLastLoginTime();
            if(newTime==null){
                newTime = new Date();
            }
            securityUserStruct.setLastLoginTimeMillis(newTime.getTime());
            securityUserStruct.setStatus(adminUser.getStatus());
            result.setUser(securityUserStruct);
            //这是用户上次登录时间
            adminUser.setLastLoginTime(new Date());
            adminUserService.updateById(adminUser);
        }
        result.setGlobalEnum(GlobalEnum.BRO_AUTHORIZED_SUCCESS);
        logger.debug("[SecurityServiceImpl][authenticate] entering username:{},password:{},result:{}",username, password, result);
        return result;
    }

    @Override
    public List<AdminMenuStruct> queryNavResources(int userId) {
        logger.debug("[SecurityServiceImpl][queryNavResources] entering userId:{}",userId);
        AdminUser wyAdminUser = adminUserService.loadById(userId);
        List<AdminResource> wyAdminResources = adminResourceService.queryResourcesByUserId(wyAdminUser);
        if(wyAdminResources==null || wyAdminResources.size()<=0){
            return new ArrayList<>();
        }
        //拼接最后返回的数据结构
        List<AdminMenuStruct> wyAdminMenuStructList = AuthorityConvertUtil.convert2AuthorityMenuStruct(wyAdminResources);
        logger.info("[SecurityServiceImpl][queryNavResources] desc userId:{},wyAdminMenuStructList:{}",userId,wyAdminMenuStructList);
        return wyAdminMenuStructList;
    }

    public static void main(String[] args) {
        System.out.println(DigestUtils.md5Hex("wenyanhlmy").toLowerCase());
    }

}
